package main

import (
	"fmt"
	"reflect"
)

//	            变量
//	value                        type
//
// static type  ||    concrete type
// int,string      interface所指向的具体数据类型，系统看得见

type User struct {
	Name string
	Age  int
	Id   int
}

func (u User) Call() {
	fmt.Println("user is called...")
	fmt.Printf("u = %v\n", u)
}

func reflectNum(a interface{}) {
	fmt.Println(reflect.TypeOf(a), ": ", reflect.ValueOf(a))
}
func goReflect() {
	var a int = 10
	var b interface{} = a

	reflectNum(a)
	reflectNum(b)
	var user User = User{
		Name: "Tom",
		Age:  18,
		Id:   1001,
	}
	user.Call()
	DoFiledAndMethod(user)
}

func DoFiledAndMethod(input interface{}) {
	// 获取input的type
	inputType := reflect.TypeOf(input)
	fmt.Println("inputType: ", inputType)
	//获取input的value
	inputValue := reflect.ValueOf(input)
	fmt.Println("inputValue: ", inputValue)
	//通过type获取里面的字段
	//1.获取interface的reflect.Type，通过Type得到NumField，进行遍历
	//2.得到每个field，再通过field有Interface()方法得到对应的value
	for i := 0; i < inputType.NumField(); i++ {
		field := inputType.Field(i)
		value := inputValue.Field(i).Interface()
		fmt.Printf("field name: %s, field type: %s, field value: %v\n", field.Name, field.Type, value)
	}

	// 通过type获取里面的方法
	fmt.Println("inputType.NumMethod(): ", inputType.NumMethod())
	for i := 0; i < inputType.NumMethod(); i++ {
		method := inputType.Method(i)
		fmt.Printf("method name: %s, method type: %s\n", method.Name, method.Type)
	}
}
